---
title: 规范化与并发
---
## 函数依赖
给定一个 X ，能唯一确定一个 Y ，就称 X 确定 Y，或者说 Y 依赖 X ，例如 $Y = X \times X$ 函数。

函数依赖又可以扩展以下两种规则：
* 部分函数依赖：A 可确定 C，(A,B) 也可确定 C，<RedSpan>(A,B) 中的一部分（即 A） 可以确定 C</RedSpan>，称为部分函数依赖。
* 传递函数依赖：当 A 和 B 不等价时，<RedSpan>A 可确定 B，B 可确定 C，则 A 可确定 C</RedSpan>，是传递函数依赖；若 A 和 B 等价，则不存在传递依赖，直接就可以确定 C。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/ruankao202410212231231.png"/>

### 函数依赖的公理系统（Armstrong）
设关系模式 $R<U,F>$，U 是关系模式 R 的属性全集，F 是关系模式 R 的一个函数依赖集。对于 $R<U,F>$ 来说有以下的：

* 自反律：若 $Y \subseteq X \subseteq U$，则 $X \rightarrow Y$为 F 所逻辑蕴含。
* 增广律：若  $X \rightarrow Y$为 F 所逻辑蕴含，且 $Z \subseteq U$，则 $XZ \rightarrow YZ$为 F 所逻辑蕴含。
* 传递律：若 $X \rightarrow Y$ 和 $Y \rightarrow Z$ 所逻辑蕴含，则 $X \rightarrow Z$ 为 F 所逻辑蕴含。
* 合并规律：若 $X \rightarrow Y$，$X \rightarrow Z$ ,则 $X \rightarrow YZ$ 为 F 所逻辑蕴含。
* 伪传规律：若 $X \rightarrow Y$，$WY \rightarrow Z$ ,则 $XW \rightarrow Z$ 为 F 所逻辑蕴含。
* 分解规律：若 $X \rightarrow Y$，$Z \subseteq Y$ ，则 $X \rightarrow Z$ 为 F 所逻辑蕴含。
:::tip
$\subseteq$ 是属于的意思，$Y \subseteq X$即 X 包含 Y。
:::

## 键与约束
* 超键：能<RedSpan>唯一标识</RedSpan>此表的属性的组合。不管有没有冗余。
* 候选键：超键中 <RedSpan>去掉冗余的属性</RedSpan>，剩余的属性就是候选键。
* 主键：<RedSpan>任选一个候选键</RedSpan>，即可作为主键。只有一个的时候，候选键就是主键。
* 外键：<RedSpan>其它表中的主键</RedSpan>
* 主属性：<RedSpan>候选键内的属性为主属性</RedSpan>，其它属性为非主属性。

:::tip
主键、主码，键与码是一个东西。
:::
* 实体完整性约束:即 <RedSpan>主键约束，主键的值不能为空，也不能重复</RedSpan>。
* 参照完整性约束：即外键约束，<RedSpan>外键必须是其它表中已经存在的主键的值，或者为空</RedSpan>。
* 用户自定义完整性:<RedSpan>自定义表达式约束</RedSpan>，如设置年龄属性的值必须在 0 到 150 之间。



## 范式

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/img/202410241708065.png"/>
范式是层层递进的，都是通过分解实现的。这里用一个例子来举例：<br/>
例子：用一个单一的关系模式学生来描述学校的教务系统：学生（学号、姓名、系号，系主任姓名、课程号、成绩），
存在依赖关系（学号 $\rightarrow$ 姓名，学号$ \rightarrow $所在系，系号$ \rightarrow $系主任名称，学号$ \rightarrow $课程号，(学号,课程号)$ \rightarrow $成绩）

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/ruankao202410212316147.png"/>


这里的主键为一个联合主键（学号，课程号）
### 第一范式 1NF
关系中的 <RedSpan>每一个分量必须是一个不可分的数据项</RedSpan>。通俗地讲，第一范式就是表中不允许有小表的存在。比如，对于如下的员工表，就不属于第一范式。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/ruankao202410212311737.png"/>

即每一个属性都是简单属性，而不是复合属性。


### 第二范式 2NF
如果 <RedSpan>关系 R 属于 1NF，且每一个非主属性完全函数依赖任何一个候选码</RedSpan>，则 R 属于 2NF。

通俗地说，2 NF就是在 1NF 的基础上，表中的 <RedSpan>每一个非主属性不会依赖复合主键中的某一个列。</RedSpan>

按照定义，上面的学生表就不满足 2NF，因为学号不能完全确定课程号和成绩（每位学生可以选多门课）


* 学号 $\rightarrow$ 姓名，学号 $\rightarrow $所在系，学号$ \rightarrow $课程号，这几个都是部分函数依赖。

* (学号,课程号) $\rightarrow$ 成绩 是完全函数依赖。
:::tip
部分函数依赖只存在于联合主键中，对于单属性的主键来书，必然是 2NF。
:::

将学生表分解为：
1. 学生(学号，学生姓名，系编号，系名，系主任)
2. 选课（学号，课程号，成绩）
这样每张表都属于 2NF。

### 第三范式 3NF
在 <RedSpan>满足 1NF 的基础上，表中不存在非主属性对码的传递依赖</RedSpan>

继续拿上面的实例举例，学生关系就不属于 3NF，因为学生无法直接决定系主任和系名，是由 学号 $\rightarrow$ 系编号，再由 系编号 $\rightarrow$ 系主任，系编号 $\rightarrow$ 系名，因此存在非主属性对主属性的传递依赖。

<RedSpan>将学生表进一步分解为</RedSpan>：
1. 学生(学号，姓名，系号)
2. 系(系号，系名，系主任)
2. 选课(学号，课程号，成绩)
每张条都属于 3NF

### BC 范式

BC 范式 BCNF，是指 <RedSpan>在第三范式的基础上进一步消除主属性对于码的部分函数依赖和传递依赖。</RedSpan>

:::tip
BC 范式针对有多个候选关键字的情况。
:::
通俗的来说，就是 <RedSpan>在每一种情况下，每一个依赖的左边决定因素都必然包含候选键，</RedSpan>如下：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/ruankao202410212344708.png"/>

上图中，候选键有两种情况：组合键(S,T)或者(s,J)，依赖集为

$\{$SJ $\rightarrow$ T,T $\rightarrow$J$\}$，
可知，STJ 三个属性都是主属性，因此其达到了 3NF（无非主属性），然而，第二种情况，即(S,J) 为候选键的时候，对于依赖 T $\rightarrow$ J，T在这种情况不是候选键，即 T $\rightarrow$ J 的决定因素不包含任意候选码，因此上图不是 BCNF。

要使上图关系模式转换为 BCNF 也很简单，只需要将依赖 $T \rightarrow J$ 变为 $TS \rightarrow J$, 这样其左边决定因素就包含了候选键之一 S。


:::tip title='候选关键字求法'
根据依赖集，找出 <RedSpan>从未在右边出现过的属性</RedSpan>，必然是候选关键字之一，以该属性为基础，根据依赖集依次扩展，看 <RedSpan>能否遍历所有属性</RedSpan>，将无法遍历的加入候选键中。

这里是允许传递依赖、部分依赖的。

:::

## 模式分解
范式之间的转换一般是通过拆分属性，即模式分解，将具有部分函数依赖和传递依赖的属性分离出来，来达到进一步的优化，一般分为以下两种：

保持函数依赖分解：对于关系模式 R，有依赖集 F，若对 R 进行分解，<RedSpan>分解出来的多个关系模式，保持原来的依赖集不变</RedSpan>则为保持函数依赖的分解。另外，注意要消除掉冗余依赖（如传递依赖）
> 例如：设原关系模式 R(A,B,C),依赖集 F(A $\rightarrow$ B,B$\rightarrow$C,A$\rightarrow$C),将其分解为两个关系模式 $R_1$(A,B) 和 $R_2$(B,C)，此时 $R_1$ 中保持函数依赖 A$\rightarrow$B,R2保持依赖 B$\rightarrow$C,说明分解后的 $R1$和$R2$ 是保持函数依赖的分解，因为 A$\rightarrow$C 这个函数依赖实际是一个冗余依赖。

无损分解：分解后的关系模式能够还原出原关系模式，能就是无损分解，不能就是有损。

当分解为 <RedSpan>两个关系模式</RedSpan>，可以通过以下定理判断是否无损分解。

如果R的分解为 p=$\{R_1,R_2\}$，F 为 R 所满足的函数依赖集合，分解 p 具有 <RedSpan>无损连接性的充分必要条件是 $R_1 \cap R_2 \rightarrow (R_1 - R_2)$ 或者  $R_1 \cap R_2 \rightarrow (R_2 - R_1)$</RedSpan>

